#include "Delay.h"

/**
    ******************************************************************************
    * 函数名称：Delay_us
    * 功能描述：微秒级精确延时（基于SysTick定时器）
    * 输入参数：xus - 延时时长（0~1864134 us）
    * 返回值  ：无
    * 详细说明：
    * 1. 基于9MHz系统时钟（1us=9个时钟周期）
    * 2. 使用24位递减计数器（SysTick->LOAD）
    * 3. 最大延时受计数器位数限制（2^24/9≈1864134us）
    * 注意事项：
    * - 不适用于中断服务函数中调用
    * - 实际延时会有±3个时钟周期的误差
    * - 修改系统时钟频率需同步调整计算公式
    * 调用示例：
    *   Delay_us(100); // 精确延时100微秒
    ******************************************************************************
**/
void Delay_us(uint32_t xus)
{
    SysTick->CTRL = 0;                      // 关闭SysTick（清空控制寄存器）
    SysTick->LOAD = (9 * xus) - 1;          // 设置重装载值（9MHz时钟）
    SysTick->VAL  = 0x00;                    // 清空计数器（写任何值都会清零）
    SysTick->CTRL = 0x00000005;             // 启用SysTick（使用内核时钟）
    while(!(SysTick->CTRL & 0x00010000));   // 等待计数完成（检查COUNTFLAG）
    SysTick->CTRL = 0;                      // 关闭SysTick
}

/**
    ******************************************************************************
    * 函数名称：Delay_ms
    * 功能描述：毫秒级延时（基于Delay_us）
    * 输入参数：xms - 延时时长（0~1864 ms）
    * 返回值  ：无
    * 详细说明：
    * 1. 通过循环调用Delay_us(1000)实现
    * 2. 存在函数调用开销，精度略低于Delay_us
    * 3. 最大延时受Delay_us限制
    * 调用示例：
    *   Delay_ms(500); // 延时500毫秒
    ******************************************************************************
**/
void Delay_ms(uint32_t xms)
{
    SysTick->CTRL = 0;                      // 关闭SysTick（清空控制寄存器）
    SysTick->LOAD = (9*1000 * xms) - 1;     // 设置重装载值（9MHz时钟）
    SysTick->VAL  = 0x00;                    // 清空计数器（写任何值都会清零）
    SysTick->CTRL = 0x00000001;             // 启用SysTick（使用内核时钟）
    while(!(SysTick->CTRL & 0x00010000));   // 等待计数完成（检查COUNTFLAG）
    SysTick->CTRL = 0;  
}

/**
    ******************************************************************************
    * 函数名称：Delay_s
    * 功能描述：秒级延时（基于Delay_ms）
    * 输入参数：xs - 延时时长（0~1 s）
    * 返回值  ：无
    * 详细说明：
    * 1. 通过循环调用Delay_ms(1000)实现
    * 2. 适用于非精确长延时场景
    * 注意事项：
    * - 长时间阻塞式延时会影响系统实时性
    * - 需要更精确的计时建议使用硬件定时器
    * 调用示例：
    *   Delay_s(1); // 延时1秒
    ******************************************************************************
**/
void Delay_s(uint32_t xs)
{
    SysTick->CTRL = 0;                      // 关闭SysTick（清空控制寄存器）
    SysTick->LOAD = (9*1000000 * xs) - 1;// 设置重装载值（9MHz时钟）
    SysTick->VAL  = 0x00;                    // 清空计数器（写任何值都会清零）
    SysTick->CTRL = 0x00000001;             // 启用SysTick（使用内核时钟）
    while(!(SysTick->CTRL & 0x00010000));   // 等待计数完成（检查COUNTFLAG）
    SysTick->CTRL = 0;
}
